extends layout

block content
  h2 Sub Docs
  :markdown
    Subdocuments are documents embedded in other documents. In Mongoose, this
    means you can nest schemas in other schemas. Mongoose has two
    distinct notions of subdocuments: arrays of subdocuments and single nested
    subdocuments.
    ```javascript
    var childSchema = new Schema({ name: 'string' });

    var parentSchema = new Schema({
      // Array of subdocuments
      children: [childSchema],
      // Single nested subdocuments. Caveat: single nested subdocs only work
      // in mongoose >= 4.2.0
      child: childSchema
    });
    ```
  :markdown
    Subdocuments are similar to normal documents. Nested schemas can have
    [middleware](./middleware.html), [custom validation logic](./validation.html),
    virtuals, and any other feature top-level schemas can use. The major
    difference is that subdocuments are
    not saved individually, they are saved whenever their top-level parent
    document is saved.
    ```javascript
    var Parent = mongoose.model('Parent', parentSchema);
    var parent = new Parent({ children: [{ name: 'Matt' }, { name: 'Sarah' }] })
    parent.children[0].name = 'Matthew';

    // `parent.children[0].save()` is a no-op, it triggers middleware but
    // does **not** actually save the subdocument. You need to save the parent
    // doc.
    parent.save(callback);
    ```
  :markdown
    Subdocuments have `save` and `validate` [middleware](./middleware.html)
    just like top-level documents. Calling `save()` on the parent document triggers
    the `save()` middleware for all its subdocuments, and the same for `validate()`
    middleware.

    ```javascript
    childSchema.pre('save', function (next) {
      if ('invalid' == this.name) {
        return next(new Error('#sadpanda'));
      }
      next();
    });

    var parent = new Parent({ children: [{ name: 'invalid' }] });
    parent.save(function (err) {
      console.log(err.message) // #sadpanda
    });
    ```
  :markdown
    Subdocuments' `pre('save')` and `pre('validate')` middleware execute
    **before** the top-level document's `pre('save')` but **after** the
    top-level document's `pre('validate')` middleware. This is because validating
    before `save()` is actually a piece of built-in middleware.

    ```javascript
    // Below code will print out 1-4 in order
    var childSchema = new mongoose.Schema({ name: 'string' });

    childSchema.pre('validate', function(next) {
      console.log('2');
      next();
    });

    childSchema.pre('save', function(next) {
      console.log('3');
      next();
    });

    var parentSchema = new mongoose.Schema({
      child: childSchema,
        });

    parentSchema.pre('validate', function(next) {
      console.log('1');
      next();
    });

    parentSchema.pre('save', function(next) {
      console.log('4');
      next();
    });
    ```

  h3 Finding a sub-document
  :markdown
    Each subdocument has an `_id` by default. Mongoose document arrays have a
    special [id](./api.html#types_documentarray_MongooseDocumentArray-id) method
    for searching a document array to find a document with a given `_id`.
    ```javascript
    var doc = parent.children.id(_id);
    ```
  h3 Adding sub-docs to arrays
  :markdown
    MongooseArray methods such as
    [push](./api.html#types_array_MongooseArray.push),
    [unshift](./api.html#types_array_MongooseArray.unshift),
    [addToSet](./api.html#types_array_MongooseArray.addToSet),
    and others cast arguments to their proper types transparently:
    ```javascript
    var Parent = mongoose.model('Parent');
    var parent = new Parent;

    // create a comment
    parent.children.push({ name: 'Liesl' });
    var subdoc = parent.children[0];
    console.log(subdoc) // { _id: '501d86090d371bab2c0341c5', name: 'Liesl' }
    subdoc.isNew; // true

    parent.save(function (err) {
      if (err) return handleError(err)
      console.log('Success!');
    });
    ```
  :markdown
    Sub-docs may also be created without adding them to the array by using the
    [create](./api.html#types_documentarray_MongooseDocumentArray.create)
    method of MongooseArrays.
    ```javascript
    var newdoc = parent.children.create({ name: 'Aaron' });
    ```
  h3 Removing subdocs
  :markdown
    Each subdocument has it's own
    [remove](./api.html#types_embedded_EmbeddedDocument-remove) method. For
    an array subdocument, this is equivalent to calling `.pull()` on the
    subdocument. For a single nested subdocument, `remove()` is equivalent
    to setting the subdocument to `null`.
    ```javascript
    // Equivalent to `parent.children.pull(_id)`
    parent.children.id(_id).remove();
    // Equivalent to `parent.child = null`
    parent.child.remove();
    parent.save(function (err) {
      if (err) return handleError(err);
      console.log('the subdocs were removed');
    });
    ```
  h4#altsyntax Alternate declaration syntax for arrays
  :markdown
    If you create a schema with an array of objects, mongoose will automatically
    convert the object to a schema for you:
    ```javascript
    var parentSchema = new Schema({
      children: [{ name: 'string' }]
    });
    // Equivalent
    var parentSchema = new Schema({
      children: [new Schema({ name: 'string' })]
    });
    ```
  h3#next Next Up
  :markdown
    Now that we've covered `Sub-documents`, let's take a look at
    [querying](./queries.html).
